﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.IO;
using System.Runtime.InteropServices;
using System.IO.Compression;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;


namespace ResourceReplace
{
    class RRProgram
    {
        static void Main(string[] args)
        {
            someMethod();
            /*String filename = @"C:\myprojs\ilookinto\cs\ILookInto\SelfDoc\bin\Debug\selfdoc.exe";
            //Open the assembly using Mono.Cecil
            using (ResourceInfo vi = new ResourceInfo())
            {
                vi.Load(filename);
                foreach (ResourceId type in vi.ResourceTypes)
                {
                    foreach (Resource resource in vi.Resources[type])
                    {
                        Console.WriteLine("{0} - {1} ({2}) - {3} byte(s)",
                            resource.TypeName, resource.Name, resource.Language, resource.Size);
                        if (resource.TypeName.Equals("FILE"))
                        {
                            resource.LoadFrom(filename);
                            byte[] b = resource.WriteAndGetBytes();
                            Console.WriteLine(b.Length);
                            Console.Read();
                        }
                    }
                }

            }*/


            Console.Read();
        }



        [DllImport("kernel32", CharSet = CharSet.Unicode)]
        private static extern IntPtr BeginUpdateResource(String pFileName, bool
        bDeleteExistingResources);

        [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern int UpdateResource(IntPtr hUpdate,
        System.Text.StringBuilder lpType, System.Text.StringBuilder lpName, Int16 wLanguage, Byte[] lpData, int cbData);

        [DllImport("kernel32", SetLastError = true)]
        private static extern int EndUpdateResource(IntPtr hUpdate, bool fDiscard);


        private static void someMethod()
        {
           
            //I have only been able to get UpperCase strings to work.
            //If the strings are not uppercase then the resources will
            //be replaced instead of added.

            //UpperCase String.
            System.Text.StringBuilder resType =
            new System.Text.StringBuilder("FILE");

            //UpperCase String.
            System.Text.StringBuilder resName =
            new System.Text.StringBuilder("file.zip");
            MemoryStream ms = zip(null, new String[] {@"c:\docs\Oscar.docx"});
            
            Byte[] someByteArray = ms.ToArray();

            IntPtr hResource = BeginUpdateResource(@"C:\myprojs\ilookinto\cs\ILookInto\SelfDoc\bin\x86\CompackSelfDoc\selfdoc.exe", false);

            UpdateResource(hResource, resType, resName, 1033, someByteArray,
            someByteArray.Length);

            EndUpdateResource(hResource, false);

        }

        public static MemoryStream zip(string password, String[] contents)
        {
            
            MemoryStream fsOut = new MemoryStream();
            if (!contents[0].EndsWith(".zip"))
            {
                ZipOutputStream zipStream = new ZipOutputStream(fsOut);

                zipStream.SetLevel(3); //0-9, 9 being the highest level of compression

                zipStream.Password = password;	// optional. Null is the same as not setting.

                foreach (string filename in contents)
                {
                    string entryName = ZipEntry.CleanName(filename); // Removes drive from name and fixes slash direction
                    ZipEntry newEntry = new ZipEntry(entryName);
                    newEntry.DateTime = DateTime.Now;

                    // Specifying the AESKeySize triggers AES encryption. Allowable values are 0 (off), 128 or 256.
                    //   newEntry.AESKeySize = 256;

                    // To permit the zip to be unpacked by built-in extractor in WinXP and Server2003, WinZip 8, Java, and other older code,
                    // you need to do one of the following: Specify UseZip64.Off, or set the Size.
                    // If the file may be bigger than 4GB, or you do not need WinXP built-in compatibility, you do not need either,
                    // but the zip will be in Zip64 format which not all utilities can understand.
                    //   zipStream.UseZip64 = UseZip64.Off;

                    newEntry.Size = new FileInfo(filename).Length;

                    zipStream.PutNextEntry(newEntry);

                    // Zip the file in buffered chunks
                    // the "using" will close the stream even if an exception occurs
                    byte[] buffer = new byte[4096];
                    using (FileStream streamReader = File.OpenRead(filename))
                    {
                        StreamUtils.Copy(streamReader, zipStream, buffer);
                    }
                    zipStream.CloseEntry();
                }
                zipStream.IsStreamOwner = true;	// Makes the Close also Close the underlying stream
                zipStream.Close();
            }
            else // zipped file.
            {
                using (FileStream streamReader = File.OpenRead(contents[0]))
                {

                    byte[] buffer = new byte[4096];
                    StreamUtils.Copy(streamReader, fsOut, buffer);
                }

            }
             //fsOut.Seek(0, SeekOrigin.Begin);
             return fsOut;
            
        }
       

    }
}
